package cn.xutongxue.gtms.service.impl;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

import cn.dev33.satoken.stp.StpUtil;
import cn.xutongxue.gtms.entity.SelectUserThesis;
import cn.xutongxue.gtms.entity.dto.thesis.ThesisTeacherDto;
import cn.xutongxue.gtms.entity.vo.ApplyVo;
import cn.xutongxue.gtms.entity.vo.ThesisTeacherVo;

import cn.hutool.core.bean.BeanUtil;
import cn.xutongxue.gtms.base.DeleteRequest;
import cn.xutongxue.gtms.base.Errors;
import cn.xutongxue.gtms.entity.PostUserThesis;
import cn.xutongxue.gtms.entity.User;
import cn.xutongxue.gtms.entity.dto.thesis.PostThesisRequest;
import cn.xutongxue.gtms.entity.dto.thesis.ThesisQueryRequest;
import cn.xutongxue.gtms.entity.vo.ThesisVo;
import cn.xutongxue.gtms.exception.BusinessException;
import cn.xutongxue.gtms.exception.ThrowUtils;
import cn.xutongxue.gtms.mapper.PostUserThesisMapper;
import cn.xutongxue.gtms.mapper.SelectUserThesisMapper;
import cn.xutongxue.gtms.mapper.UserMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.xutongxue.gtms.entity.Thesis;
import cn.xutongxue.gtms.service.ThesisService;
import cn.xutongxue.gtms.mapper.ThesisMapper;
import com.github.yulichang.query.MPJLambdaQueryWrapper;
import com.github.yulichang.query.MPJQueryWrapper;
import com.github.yulichang.toolkit.JoinWrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

/**
* @author Administrator
* @description 针对表【thesis】的数据库操作Service实现
* @createDate 2023-08-10 14:13:49
*/
@Service
public class ThesisServiceImpl extends ServiceImpl<ThesisMapper, Thesis>
    implements ThesisService{

    @Resource
    private ThesisMapper thesisMapper;
    @Resource
    private PostUserThesisMapper postUserThesisMapper;

    @Resource
    private UserMapper userMapper;

    @Resource
    private SelectUserThesisMapper selectUserThesisMapper;

    @Override
    @Transactional
    public boolean postThesis(PostThesisRequest postThesisRequest, HttpServletRequest request) {
        if (postThesisRequest == null) {
            throw new BusinessException(Errors.PARAMS_ERROR);
        }
        String title = postThesisRequest.getTitle();
        if (StringUtils.isAnyBlank(title)) {
            throw new BusinessException(Errors.PARAMS_ERROR);
        }
        // 保存Thesis
        Thesis thesis = new Thesis();
        BeanUtil.copyProperties(postThesisRequest, thesis);
        thesis.setIsDeleted(0);
        thesis.setState(0);
        save(thesis);

        // 保存map
        PostUserThesis postUserThesis = new PostUserThesis();
        postUserThesis.setThesisId(thesis.getId());
        postUserThesis.setUserId(Long.valueOf((String) StpUtil.getLoginId()));
        postUserThesisMapper.insert(postUserThesis);
        ThrowUtils.throwIf(thesis.getId() == null || postUserThesis.getId() == null, Errors.OPERATION_ERROR);
        return true;
    }

    @Override
    @Transactional
    public boolean deleteThesis(DeleteRequest deleteRequest) {
        removeById(deleteRequest);
        LambdaQueryWrapper<PostUserThesis> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PostUserThesis::getThesisId, deleteRequest.getId());
        ThrowUtils.throwIf(postUserThesisMapper.delete(wrapper) < 1, Errors.OPERATION_ERROR);
        return true;
    }

    @Override
    public Page<ThesisVo> listThesisByPage(ThesisQueryRequest thesisQueryRequest) {
        if (thesisQueryRequest == null) {
            throw new BusinessException(Errors.PARAMS_ERROR);
        }

        long size = thesisQueryRequest.getSize();
        long current = thesisQueryRequest.getCurrent();
        String title = thesisQueryRequest.getTitle();
        String mentor = thesisQueryRequest.getMentor();
        Integer state = thesisQueryRequest.getState();
        MPJLambdaWrapper<Thesis> wrapper = new MPJLambdaWrapper<>();
        wrapper.selectAll(Thesis.class)
                .select(User::getUsername, User::getEmail, User::getPhone)
                .leftJoin(PostUserThesis.class, PostUserThesis::getThesisId, Thesis::getId)
                .leftJoin(User.class, User::getId, PostUserThesis::getUserId)
                .like(StringUtils.isNotBlank(title), Thesis::getTitle, title)
                .like(StringUtils.isNotBlank(mentor), User::getUsername, mentor)
                .eq(state != null && state != 3, Thesis::getState, state);
        return thesisMapper.selectJoinPage(new Page<>(current,size), ThesisVo.class, wrapper);
    }

    @Override
    public Page<ThesisTeacherVo> listThesisByTeacherId(Long id, Integer current, Integer size) {
        Page<ThesisTeacherDto> thesisTeacherDtoPage = thesisMapper.selectThesisVoByTeacherId(new Page<>(current, size), id);
        Page<ThesisTeacherVo> teacherVoPage = new Page<>(thesisTeacherDtoPage.getCurrent(), thesisTeacherDtoPage.getSize(), thesisTeacherDtoPage.getTotal());
        teacherVoPage.setRecords(ThesisDto2Vo(thesisTeacherDtoPage.getRecords()));
        return teacherVoPage;
    }

    @Override
    public Page<ThesisVo> searchThesisByAll(ThesisQueryRequest thesisQueryRequest) {
        return null;
    }

    @Transactional
    @Override
    public Boolean selectThesis(Long thesisId) {
        // 判断是否已选
        LambdaQueryWrapper<SelectUserThesis> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SelectUserThesis::getThesisId, thesisId);
        ThrowUtils.throwIf(selectUserThesisMapper.selectCount(wrapper) > 0, new BusinessException(50000, "无法选择多个课题"));

        // 修改论文状态
        Thesis thesis = getById(thesisId);
        thesis.setState(1);
        // 添加申请信息到审核表
        SelectUserThesis selectUserThesis = new SelectUserThesis();
        selectUserThesis.setUserId(StpUtil.getLoginIdAsLong());
        selectUserThesis.setThesisId(thesisId);
        // 如果失败抛出异常触发事务回滚
        ThrowUtils.throwIf(!updateById(thesis), Errors.OPERATION_ERROR);
        ThrowUtils.throwIf(selectUserThesisMapper.insert(selectUserThesis) < 1, Errors.OPERATION_ERROR);
        return true;
    }

    @Override
    public Page<ApplyVo> applyList(Long teacherId, Integer current, Integer size) {

        MPJLambdaWrapper<Thesis> wrapper = new MPJLambdaWrapper<>();
        wrapper.selectFilter(Thesis.class, i -> !i.getColumn().equals("state"))
                .select(User::getUsername)
                .select(SelectUserThesis::getState)
                .leftJoin(SelectUserThesis.class, SelectUserThesis::getThesisId, Thesis::getId)
                .leftJoin(User.class, User::getId, SelectUserThesis::getUserId)
                .leftJoin(PostUserThesis.class, PostUserThesis::getThesisId, Thesis::getId)
                .eq(PostUserThesis::getUserId, teacherId);
        Page<ApplyVo> applyVoPage = thesisMapper.selectJoinPage(new Page<>(current, size), ApplyVo.class, wrapper);

        // 排序 null 在前面
        List<ApplyVo> collect = applyVoPage.getRecords()
                .stream()
                .sorted(Comparator.comparing(ApplyVo::getState, Comparator.nullsFirst(Comparator.naturalOrder())))
                .collect(Collectors.toList());
        applyVoPage.setRecords(collect);
        return applyVoPage;
    }

    @Transactional
    @Override
    public Boolean audit(Long thesisId, Integer state) {
        int thesisState = -1;
        // 如果同意
        if (state == 0) {
            thesisState = 2;
        } else if (state == 1) {
            thesisState = 0;
        } else {
            throw new BusinessException(Errors.PARAMS_ERROR);
        }

        LambdaQueryWrapper<SelectUserThesis> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SelectUserThesis::getThesisId, thesisId);
        SelectUserThesis selectUserThesis = selectUserThesisMapper.selectOne(wrapper);

        // 修改论文状态
        Thesis thesis = getById(thesisId);
        thesis.setState(thesisState);
        // 修改失败抛出异常触发事务回滚
        ThrowUtils.throwIf(!updateById(thesis), Errors.OPERATION_ERROR);
        // 不同意从中间表删除
        if (state != 0) {
            ThrowUtils.throwIf(selectUserThesisMapper.deleteById(selectUserThesis) < 1, Errors.OPERATION_ERROR);
        } else {
            selectUserThesis.setState(0);
            ThrowUtils.throwIf(selectUserThesisMapper.updateById(selectUserThesis) < 1, Errors.OPERATION_ERROR);
        }
        // ThrowUtils.throwIf(selectUserThesisMapper.delete(wrapper) < 1, Errors.OPERATION_ERROR);
        // ThrowUtils.throwIf(selectUserThesisMapper.updateById(selectUserThesis) < 1, Errors.OPERATION_ERROR);
        return true;
    }

    @Override
    public ThesisVo getThesisInfo() {
        Long studentId = StpUtil.getLoginIdAsLong();
        MPJLambdaWrapper<Thesis> wrapper = new MPJLambdaWrapper<>();

        wrapper.selectAll(Thesis.class)
                .select(User::getUsername, User::getEmail, User::getPhone)
                .leftJoin(PostUserThesis.class, PostUserThesis::getThesisId, Thesis::getId)
                .leftJoin(User.class, User::getId, PostUserThesis::getUserId)
                .leftJoin(SelectUserThesis.class, SelectUserThesis::getThesisId, Thesis::getId)
                .eq(SelectUserThesis::getUserId, studentId)
                .eq(SelectUserThesis::getState, 0);
        return thesisMapper.selectJoinOne(ThesisVo.class, wrapper);
    }

    private List<ThesisTeacherVo> ThesisDto2Vo(List<ThesisTeacherDto> records) {
        List<ThesisTeacherVo> list = new ArrayList<>();
        for (ThesisTeacherDto dto : records) {
            ThesisTeacherVo thesisTeacherVo = new ThesisTeacherVo();
            BeanUtil.copyProperties(dto, thesisTeacherVo);
            if (dto.getSelectUserId() != null) {
                User user = userMapper.selectById(dto.getSelectUserId());
                thesisTeacherVo.setUsername(user.getUsername());
            }
            list.add(thesisTeacherVo);
        }
        return list;
    }
}




